package com.gitee.chessboard.scan.model;

import com.gitee.chessboard.utils.StringUtils;

import java.io.IOException;
import java.net.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * jar、war文件的对象
 *
 * @author 敲代码的旺财
 * @date 2021/12/7 16:11
 */
public class JarFileModel implements AutoCloseable{

    private JarFile jarFile;
    private String jarFileUrl;
    private String rootEntryPath;
    private boolean closeJarFile;

    @Override
    public void close() {
        if (closeJarFile) {
            try {
                jarFile.close();
            } catch (IOException e) {
                throw new RuntimeException("关闭流失败", e);
            }
        }
    }

    public JarFileModel() {
    }

    public JarFileModel(Builder builder) {
        this.jarFile = builder.jarFile;
        this.jarFileUrl = builder.jarFileUrl;
        this.rootEntryPath = builder.rootEntryPath;
        this.closeJarFile = builder.closeJarFile;
    }

    public JarFile getJarFile() {
        return jarFile;
    }

    public void setJarFile(JarFile jarFile) {
        this.jarFile = jarFile;
    }

    public String getJarFileUrl() {
        return jarFileUrl;
    }

    public void setJarFileUrl(String jarFileUrl) {
        this.jarFileUrl = jarFileUrl;
    }

    public String getRootEntryPath() {
        return rootEntryPath;
    }

    public void setRootEntryPath(String rootEntryPath) {
        this.rootEntryPath = rootEntryPath;
    }

    public boolean isCloseJarFile() {
        return closeJarFile;
    }

    public void setCloseJarFile(boolean closeJarFile) {
        this.closeJarFile = closeJarFile;
    }

    public static class Builder {
        private JarFile jarFile;
        private String jarFileUrl;
        private String rootEntryPath;
        private boolean closeJarFile;

        public Builder() {
        }

        public JarFileModel build() {
            return new JarFileModel(this);
        }

        public Builder setUrl(URL url) throws IOException {
            //读取资源
            URLConnection con = url.openConnection();
            if (con instanceof JarURLConnection) {
                //正常的jar、war文件都会走这里
                JarURLConnection jarCon = (JarURLConnection) con;
                //如果是个网络资源就不缓存到虚拟机中
                jarCon.setUseCaches(jarCon.getClass().getSimpleName().startsWith("JNLP"));
                this.jarFile = jarCon.getJarFile();
                this.jarFileUrl = jarCon.getJarFileURL().toExternalForm();
                JarEntry jarEntry = jarCon.getJarEntry();
                this.rootEntryPath = jarEntry != null ? jarEntry.getName() : "";
                this.closeJarFile = !jarCon.getUseCaches();
            } else {
                String urlFile = url.getFile();
                //当做war包来处理，*/是war包在URL中的分隔符
                int separatorIndex = urlFile.indexOf("*/");
                if (separatorIndex == -1) {
                    //没有查询到，就当做jar包来处理，!/是jar包在URL中的分隔符
                    separatorIndex = urlFile.indexOf("!/");
                }
                if (separatorIndex != -1) {
                    //能找到分隔符，那么就是war文件或者jar文件
                    this.jarFileUrl = urlFile.substring(0, separatorIndex);
                    //加2是因为  */和!/也要算在里面  这两个都是2字符
                    this.rootEntryPath = urlFile.substring(separatorIndex + 2);
                    if (this.jarFileUrl.startsWith("file:")) {
                        try {
                            this.jarFile = new JarFile(new URI(StringUtils.replace(this.jarFileUrl, " ", "%20")).getSchemeSpecificPart());
                        } catch (URISyntaxException ex) {
                            //抛出异常就截取掉 file: 当做普通的jar文件处理
                            this.jarFile = new JarFile(this.jarFileUrl.substring("file:".length()));
                        }
                    } else {
                        this.jarFile = new JarFile(this.jarFileUrl);
                    }
                } else {
                    this.jarFile = new JarFile(urlFile);
                    this.jarFileUrl = urlFile;
                    this.rootEntryPath = "";
                }
                this.closeJarFile = true;
            }
            return this;
        }

        public Builder setJarFile(JarFile jarFile) {
            this.jarFile = jarFile;
            return this;
        }

        public Builder setJarFileUrl(String jarFileUrl) {
            this.jarFileUrl = jarFileUrl;
            return this;
        }

        public Builder setRootEntryPath(String rootEntryPath) {
            this.rootEntryPath = rootEntryPath;
            return this;
        }

        public Builder setCloseJarFile(boolean closeJarFile) {
            this.closeJarFile = closeJarFile;
            return this;
        }
    }

}
